﻿// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！


using MailKit.Net.Smtp;
using MailKit.Security;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MimeKit;
using Admin.NET.Core.Service;
namespace IES.NET.Application;

/// <summary>
/// 邮件附件模型
/// </summary>
public class EmailAttachment
{
    /// <summary>
    /// 文件名称
    /// </summary>
    [Required]
    public string FileName { get; set; }

    /// <summary>
    /// 文件内容 (Base64编码)
    /// </summary>
    [Required]
    public string FileContent { get; set; }

    /// <summary>
    /// 文件类型 (MIME类型)
    /// </summary>
    public string ContentType { get; set; }


}

[ApiDescriptionSettings(ApplicationConst.GroupName, Order = 100)]
public class EmailSendService : IDynamicApiController, ITransient
{
    private readonly EmailOptions _emailOptions;
    private readonly SysConfigService _sysConfigService;
    private readonly ILogger<EmailSendService> _logger;  // 添加日志记录
    /// <summary>
    /// 邮件主题
    /// </summary>
    [Required(ErrorMessage = "邮件主题不能为空")]
    public string Subject { get; set; }

    /// <summary>
    /// 邮件正文(HTML格式)
    /// </summary>
    [Required(ErrorMessage = "邮件正文不能为空")]
    public string HtmlContent { get; set; }

    /// <summary>
    /// 收件人邮箱地址列表
    /// </summary>
    [Required(ErrorMessage = "收件人不能为空")]
    public List<string> ToEmails { get; set; }

    /// <summary>
    /// 抄送人邮箱地址列表
    /// </summary>
    public List<string> CcEmails { get; set; }

    /// <summary>
    /// 附件列表 (文件路径或者二进制内容)
    /// </summary>
    public List<EmailAttachment> Attachments { get; set; }

    public string EmailFromName { get; set; }
    public EmailSendService(
        IOptions<EmailOptions> emailOptions,
        SysConfigService sysConfigService,
        ILogger<EmailSendService> logger)
    {
        // 添加详细的空值检查和日志
        _emailOptions = new EmailOptions
        {
            Host = "cdsgmail.somacisgraphic.com",
            Port = 25,
            EnableSsl = true,
            DefaultFromEmail = "input.fe@somacisgraphic.com",
            DefaultToEmail = "chenyu.zhang@somacisgraphic.com",
            UserName = "input.fe@somacisgraphic.com",
            Password = "initpass2008",
            DefaultFromName = "工程管理系统平台"
        };
        _sysConfigService = sysConfigService;
        
        _logger = logger;
    }

    /// <summary>
    /// 发送增强邮件(支持多收件人、抄送、附件) 📧
    /// </summary>

    [HttpPost]
    [ApiDescriptionSettings(Name = "SendEnhancedEmail")]
    [DisplayName("发送增强邮件")]
    public async Task SendEnhancedEmail([Required] EmailSendService request)
    {
        try
        {
            var message = await CreateEmailMessage(request);
            await SendEmailMessage(message);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "邮件发送失败");
            throw Oops.Oh($"邮件发送失败: {ex.Message}");
        }
    }

    private async Task<MimeMessage> CreateEmailMessage(EmailSendService request)
    {
        var message = new MimeMessage();
        if(request.EmailFromName == null || request.EmailFromName == "")
        {
            request.EmailFromName = _emailOptions.DefaultFromName;
        }
        // 设置发件人
        message.From.Add(new MailboxAddress(request.EmailFromName, _emailOptions.DefaultFromEmail));
        
        // 设置收件人
        foreach (var email in request.ToEmails)
        {
            message.To.Add(new MailboxAddress(email, email));
        }

        // 设置抄送人
        if (request.CcEmails?.Any() == true)
        {
            foreach (var email in request.CcEmails)
            {
                message.Cc.Add(new MailboxAddress(email, email));
            }
        }

        // 设置邮件主题
        message.Subject = string.IsNullOrWhiteSpace(request.Subject)
            ? await GetDefaultSubject()
            : request.Subject;

        // 构建邮件正文和附件
        var builder = new BodyBuilder { HtmlBody = request.HtmlContent };

        // 添加附件
        if (request.Attachments?.Any() == true)
        {
            foreach (var attachment in request.Attachments)
            {
                AddAttachment(builder, attachment);
            }
        }

        message.Body = builder.ToMessageBody();
        return message;
    }

    private async Task<string> GetDefaultSubject()
    {
        var webTitle = await _sysConfigService.GetConfigValue<string>(ConfigConst.SysWebTitle);
        return $"{webTitle} 系统邮件";
    }

    private void AddAttachment(BodyBuilder builder, EmailAttachment attachment)
    {
        var fileBytes = Convert.FromBase64String(attachment.FileContent);
        var contentType = string.IsNullOrWhiteSpace(attachment.ContentType)
            ? "application/octet-stream"
            : attachment.ContentType;

        builder.Attachments.Add(attachment.FileName, fileBytes, ContentType.Parse(contentType));
    }

    private async Task SendEmailMessage(MimeMessage message)
    {
        using var client = new SmtpClient();

        try
        {
            client.ServerCertificateValidationCallback = (s, c, h, e) => true;
            // 根据端口选择合适的安全连接选项
            var secureOption = GetSecureSocketOptions();

            _logger.LogInformation($"Connecting to SMTP server: {_emailOptions.Host}:{_emailOptions.Port} with {secureOption}");

            await client.ConnectAsync(_emailOptions.Host, _emailOptions.Port, secureOption);

            if (!string.IsNullOrEmpty(_emailOptions.UserName) && !string.IsNullOrEmpty(_emailOptions.Password))
            {
                await client.AuthenticateAsync(_emailOptions.UserName, _emailOptions.Password);
            }

            await client.SendAsync(message);
        }
        finally
        {
            if (client.IsConnected)
            {
                await client.DisconnectAsync(true);
            }
        }
    }

    private SecureSocketOptions GetSecureSocketOptions()
    {
        // 根据端口和SSL配置确定安全连接选项
        return _emailOptions.Port switch
        {
            25 => _emailOptions.EnableSsl ? SecureSocketOptions.StartTls : SecureSocketOptions.None,
            465 => SecureSocketOptions.SslOnConnect,
            587 => SecureSocketOptions.StartTls,
            _ => _emailOptions.EnableSsl ? SecureSocketOptions.Auto : SecureSocketOptions.None
        };
    }
}